home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / Binding / BindngH.cpp < prev    next >
Encoding:
Text File  |  1997-02-13  |  29.1 KB  |  990 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        BindngH.cpp
  3.  
  4.     Contains:    C++ Implementation for Binding Helper class.
  5.  
  6.     Owned by:    Caia Grisar
  7.  
  8.     Copyright:    © 1993 - 1996 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <14>      11/21/96    RA        Never use Apple::NoPart for AlphanumChoose
  13.         <13>      10/18/96    RA        1398111: Substitution dialog should not
  14.                                     appear for Apple's NoPart
  15.         <12>      10/10/96    RA        Moved ChangeKindAndEditor, ChangeEditor,
  16.                                     IsNoPart and GetCurrentEditorForPart to
  17.                                     BindingUtils.cpp
  18.         <11>     10/7/96    RA        1343748: Store the preferred editor and its
  19.                                     user string as a pair
  20.         <10>     10/4/96    EL        1392459: do not set NoPart as the preferred
  21.                                     editor.
  22.          <9>     9/17/96    RA        1370339: NoPart should be replacable by
  23.                                     third parties, added choose
  24.                                     kODViewerOfLastResortKind
  25.          <8>     6/27/96    RA        1361408: Compare against null viewer part
  26.                                     handler instead of
  27.                                     kODBlackBoxHandlerOfLastResort so NoPart
  28.                                     does not get in the way of alphanum choose
  29.                                     or editor over viewer preference.
  30.          <7>     6/21/96    RA        1360591: Changed viewer NS type from object
  31.                                     to value
  32.          <6>     6/12/96    RA        1356993: Check permissions before writing
  33.                                     out kODPropPreferredEditor
  34.          <5>      6/6/96    EL        1335851: GetCurrentEditorForPart don't need
  35.                                     to make a copy of Editor string. Forgot to
  36.                                     check this in last time.
  37.          <4>      6/4/96    EL        1335851: GetEditor now returns a copy, so
  38.                                     GetCurrentEditorForPart don't need to make
  39.                                     a copy.
  40.          <3>     1/26/96    VL        1170098: Removed call to IsEditorLoaded
  41.                                     because it unnecessarily loads and unloads
  42.                                     the part library.
  43.          <2>      1/8/96    CG        1299331 1.0.1: Substitution warning dlg
  44.                                     nolonger displayed in background.
  45.         <48>    10/24/95    TJ        Included TempIter.h
  46.         <47>    10/23/95    CG        #1294762 GM: Out-of-memory on close forces
  47.                                     close without saving changes
  48.                                     #1295082 GM: Crash switching editor if lib
  49.                                     can't load
  50.                                     #1295186 GM: Failure in InitPartFromStorage
  51.                                     doesn't abort editor switch
  52.                                     #1295105 GM: Fail during Editor Change can
  53.                                     leave Preferred Kind set incorrectly
  54.         <46>     10/9/95    CC        1291425: Fixed logic in
  55.                                     ChangeKindAndEditor.
  56.         <45>     10/4/95    CG        #1284324 GM: PartInfo dialog may display
  57.                                     wrong editor.
  58.         <44>     9/12/95    DM        1280020 FB1 part trans dlg mem leaks
  59.         <43>      9/8/95    CG        #1283252 FB1: Allocate memory for Editor
  60.                                     string in NoPart case.
  61.         <42>      9/8/95    TÇ        1281096 FB2:Many constants in ODTypesB
  62.                                     without kOD prefix!
  63.         <41>      9/7/95    CG        #1262630 FB2: Bad warning when NoPart
  64.                                     rebinds.
  65.         <40>     8/30/95    CG        #1244563    FB1:Missing editor needs
  66.                                     explanatory alert
  67.                                     #1215054    FB: Too many substitute editor
  68.                                     dialog
  69.                                     #1276989    FB:Leakage from SU::GetType calls
  70.         <39>     8/12/95    TÇ        1276807 Opt./Bug: use StdTypIO routines for
  71.                                     portable streaming & smaller footprint,
  72.                                     1276810 Binding writes to storage without
  73.                                     checking permissions!
  74.         <38>      8/8/95    jpa        Fixed ChooseDirectEditorForKind, which was
  75.                                     returning disposed pointers. [1275499]
  76.         <37>     6/21/95    CC        1260937: BB: ODTypeListIterator must return
  77.                                     copies of ODType values.
  78.         <36>     6/19/95    VL        1170098: Set return result for
  79.                                     GetPreferredEditorForPart to kODNULL if the
  80.                                     operation fails.
  81.         <35>     6/16/95    EL        #1254926: Don't return an editor that does
  82.                                     not exists.
  83.         <34>     6/16/95    CC        1259719: Added ChangeEditor and
  84.                                     ChangeKindAndEditor.
  85.         <33>     5/18/95    CG        #1249728 BB: BindingH.cpp needs to call
  86.                                     StdTypIO routines for ISOStr
  87.                                     #1249263 BB: BndNSUtl.cpp does not compile
  88.                                     standalone.
  89.         <32>     4/27/95    CC        1243813: Removed ShowAlert and
  90.                                     BindingDialogFilter; replaced by ShowAlert
  91.                                     in DlogUtil.
  92.         <31>     4/26/95    CG        1210975 BB: 5$ Bugs need to be evaluatedand
  93.                                     removed from Binding.
  94.         <30>     4/26/95    CG        1210975 BB: 5$ Bugs need to be evaluated
  95.                                     and removed from Binding.
  96.         <29>     4/13/95    CG        Removed obsolete #include.
  97.         <28>     3/28/95    CG        #1211901 BB:  Binding methods check for
  98.                                     null storage unit.
  99.         <27>     2/16/95    CG        #1213926 BB:binding respects preferred
  100.                                     kinds.  #1210975 BB: 5$ fixes.
  101.         <26>     2/14/95    TJ        Fixed copyright date.
  102.         <25>     2/14/95    jpa        Fixed GetContainerSuite to always return
  103.                                     NULL on failure, and to use the
  104.                                     SysPrefContainerSuites namespace. [1205141]
  105.         <24>      2/2/95    CG        #1195019:  ValueNameSpace entries are now
  106.                                     copied in and out instead of pointers being
  107.                                     passed around.
  108.         <23>     1/25/95    jpa        Fixed no-prefs crashes [1214750]
  109.         <22>     1/24/95    CG        In GetContainerSuite now check return value
  110.                                     of ValueNameSpaceGetEntry instead of return
  111.                                     parameter.  broke last build.
  112.         <21>     1/23/95    CG        #1195019: ValueNameSpace methods now take
  113.                                     ODByteArray parameter instead of ODPtr.
  114.         <20>     1/13/95    RR        Removed include of ODTypesM.xh
  115.         <19>     1/12/95    jpa        Don't use obsolete Toolbox names. [1211211]
  116.         <18>     1/10/95    CG        #1201731:  BB: Now get NoPart if a part
  117.                                     can't be loaded because of an error.
  118.         <17>    12/20/94    VL        1195012: Make Storage calls be
  119.                                     marshallable.
  120.         <16>    12/13/94    CG        #1193522: Warning dialog displayed if
  121.                                     automatic binding has occurred.
  122.         <15>     10/7/94    CG        #1184728:  Broke NoPart with last fix!
  123.         <14>     10/7/94    CG        #1184728: Binding to another part that
  124.                                     supports the same kind when original editor
  125.                                     not found now works.
  126.         <13>      9/9/94    CG        1182933: changed NoPart editor id.
  127.         <12>      9/9/94    jpa        Fixed IsEditorLoaded to call new
  128.                                     ODClassExists rather than use SOM; this fix
  129.                                     re-enables debugging of parts. [1182105]
  130.         <11>     8/24/94    CG        #1181622: Updated file ownership.
  131.         <10>     8/17/94    CG        #1181440 The View and EditorKinds name
  132.                                     spaces were changed to be of type
  133.                                     ODObjectNameSpace.
  134.          <9>     7/29/94    CG        NameSpace API changes.
  135.          <8>     7/26/94    jpa        Don't call InitObject from InitBinding.
  136.          <7>      7/1/94    CG        Changes to IsEditorLoaded.
  137.          <6>      7/1/94    CG        Added som calls to IsEditorLoaded.
  138.          <5>     6/28/94    VL        Use Translt.cpp.
  139.          <4>     6/27/94    CG        Moved IsEditorLoaded here from Prefs.
  140.                                     Removed fEv.
  141.          <3>     6/23/94    eeh        oops....include EditrSet.h
  142.          <2>     6/23/94    eeh        remove ODEditorSetIterator and EditorSet
  143.          <1>     6/20/94    CG        first checked in
  144.  
  145.     To Do:
  146.     In Progress:
  147.         
  148. */
  149.  
  150. #include <somcls.xh>
  151. #include <somcm.xh>
  152.  
  153. #ifndef __ERRORS__
  154. #include <Errors.h>
  155. #endif
  156.  
  157. #ifndef _BINDNGH_
  158. #include "BindngH.h"
  159. #endif
  160.  
  161. #ifndef _EDITRSET_
  162. #include "EditrSet.h"
  163. #endif
  164.  
  165. #ifndef _ODMEMORY_
  166. #include "ODMemory.h"
  167. #endif
  168.  
  169. #ifndef SOM_ODStorageUnit_xh
  170. #include "StorageU.xh"
  171. #endif
  172.  
  173. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  174. #include "StdDefs.xh"
  175. #endif
  176.  
  177. #ifndef SOM_Module_OpenDoc_StdProps_defined
  178. #include "StdProps.xh"
  179. #endif
  180.  
  181. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  182. #include "StdTypes.xh"
  183. #endif
  184.  
  185. #ifndef _ODUTILS_
  186. #include "ODUtils.h"
  187. #endif
  188.  
  189. #ifndef SOM_ODTranslation_xh
  190. #include "Translt.xh"
  191. #endif
  192.  
  193. #ifndef _ODSESSN_
  194. #include "ODSessn.xh"
  195. #endif
  196.  
  197. #ifndef SOM_ODValueNameSpace_xh
  198. #include "ValueNS.xh"
  199. #endif
  200.  
  201. #ifndef SOM_ODObjectNameSpace_xh
  202. #include "ObjectNS.xh"
  203. #endif
  204.  
  205. #ifndef _ORDCOLL_
  206. #include "OrdColl.h"
  207. #endif
  208.  
  209. #ifndef SOM_ODNameSpaceManager_xh
  210. #include "NmSpcMg.xh"
  211. #endif
  212.  
  213. #ifndef _EXCEPT_
  214. #include "Except.h"
  215. #endif
  216.  
  217. #ifndef _PASCLSTR_
  218. #include "PasclStr.h"
  219. #endif
  220.  
  221. #ifndef _ISOSTR_
  222. #include "ISOStr.h"
  223. #endif
  224.  
  225. #ifndef SOM_Apple_NoPart_xh
  226. #include <NoPart.xh>
  227. #endif
  228.  
  229. #ifndef SOM_ODTypeList_xh
  230. #include <TypeList.xh>
  231. #endif
  232.  
  233. #ifndef SOM_ODTypeListIterator_xh
  234. #include <TypLsItr.xh>
  235. #endif
  236.  
  237. #ifndef _BNDNSUTL_
  238. #include "BndNSUtl.h"
  239. #endif
  240.  
  241. #ifndef _ODNEWOBJ_
  242. #include <ODNewObj.h>
  243. #endif
  244.  
  245. #ifndef __DIALOGS__
  246. #include <Dialogs.h>
  247. #endif
  248.  
  249. #ifndef SOM_ODWindowState_xh
  250. #include <WinStat.xh>
  251. #endif
  252.  
  253. #ifndef SOM_ODWindow_xh
  254. #include <Window.xh>
  255. #endif
  256.  
  257. #ifndef _USERSRCM_
  258. #include <UseRsrcM.h>
  259. #endif
  260.  
  261. #ifndef _STORUTIL_
  262. #include <StorUtil.h>
  263. #endif
  264.  
  265. #ifndef _BNDNGDEF_
  266. #include "BndngDef.h"
  267. #endif
  268.  
  269. #ifndef SOM_ODFrame_xh
  270. #include <Frame.xh>
  271. #endif
  272.  
  273. #ifndef _NMSPCUTL_
  274. #include <NmSpcUtl.h>
  275. #endif
  276.  
  277. #ifndef SOM_ODDispatcher_xh
  278. #include <Disptch.xh>
  279. #endif
  280.  
  281. #ifndef _DLOGUTIL_
  282. #include <DlogUtil.h>
  283. #endif
  284.  
  285. #ifndef SOM_ODPartWrapper_xh
  286. #include <PartWrap.xh>
  287. #endif
  288.  
  289. #ifndef _DOCUTILS_
  290. #include <DocUtils.h>
  291. #endif
  292.  
  293. #ifndef _STDTYPIO_
  294. #include <StdTypIO.h>
  295. #endif
  296.  
  297. #ifndef _INFOUTIL_
  298. #include "InfoUtil.h"
  299. #endif
  300.  
  301. #ifndef _TEMPOBJ_
  302. #include <TempObj.h>
  303. #endif
  304.  
  305. #ifndef _TEMPITER_
  306. #include "TempIter.h"
  307. #endif
  308.  
  309. #ifndef SOM_ODBinding_xh
  310. #include <ODBindng.xh>
  311. #endif
  312.  
  313. #ifndef _BARRAY_
  314. #include "BArray.h"
  315. #endif
  316.  
  317. #ifndef _BINDINGUTILS_
  318. #include "BindingUtils.h"
  319. #endif
  320.  
  321. #pragma segment Binding
  322.  
  323. #undef LOGGING
  324. #define LOGGING 0
  325.  
  326. //==============================================================================
  327. // Constants
  328. //==============================================================================
  329.  
  330. #define kEditorSubstitutionList "EditorSubstitutions"
  331.  
  332. //=========================================================================
  333. // Function Prototypes
  334. //=========================================================================
  335.  
  336. ODStatic void ODPascal BindingNMResponse( NMRecPtr theNMRecPtr );
  337.  
  338. ODStatic StringPtr BuildNotificationString(ODSShort strResourceID, Str255 catString, Str255 editorString);
  339.  
  340. //==============================================================================
  341. // BindingNMResponse
  342. //==============================================================================
  343.  
  344. ODStatic void ODPascal BindingNMResponse( NMRecPtr theNMRecPtr )
  345. {
  346.     OSErr error = NMRemove(theNMRecPtr);
  347. }
  348.  
  349. //------------------------------------------------------------------------------
  350. // BuildNotificationString
  351. //------------------------------------------------------------------------------
  352.  
  353. ODStatic StringPtr BuildNotificationString(ODSShort strResourceID, Str255 catString, Str255 editorString)
  354. {
  355.     Str255 msgStr;
  356.  
  357.     StringPtr result = kODNULL;
  358.     
  359.     ODSLong savedRefNum;
  360.     BeginUsingLibraryResources(savedRefNum);
  361.  
  362.     ReplaceIntoString(strResourceID, catString, editorString, msgStr);
  363.  
  364.     if ( msgStr[0] > 0 )
  365.     {
  366.         ODULong ptrSize = msgStr[0]+1;
  367.         result = (StringPtr) ODNewPtr(ptrSize);
  368.         if ( result )
  369.             ODBlockMove((ODPtr) &msgStr, (ODPtr) result, ptrSize);
  370.     }
  371.     
  372.     EndUsingLibraryResources(savedRefNum);
  373.     
  374.     return result;
  375. }
  376.  
  377. //==============================================================================
  378. // Class Binding
  379. //==============================================================================
  380.  
  381. //------------------------------------------------------------------------------
  382. // Binding::Binding
  383. //------------------------------------------------------------------------------
  384. Binding::Binding()
  385. {
  386.     fSession            = (ODSession*) kODNULL;
  387.     fSelf                = (ODBinding*) kODNULL;
  388. }
  389.  
  390. //------------------------------------------------------------------------------
  391. // Binding::~Binding
  392. //------------------------------------------------------------------------------
  393. Binding::~Binding()
  394. {
  395.     Environment* ev = somGetGlobalEnvironment ();
  396.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  397.     nsm->DeleteNameSpace(ev, fSubstitutionList);
  398.     if ( fNMResponseUPP != kODNULL )
  399.         DisposeRoutineDescriptor(fNMResponseUPP);
  400.  
  401.     if ( fNMRecPtr )
  402.         ODDisposePtr((ODPtr) fNMRecPtr->nmStr);
  403.     ODDisposePtr(fNMRecPtr);
  404. }
  405.  
  406. //------------------------------------------------------------------------------
  407. // Binding::InitBinding
  408. //------------------------------------------------------------------------------
  409. void Binding::InitBinding(ODSession* session )
  410. {
  411.     Environment* ev = somGetGlobalEnvironment ();
  412.     
  413.     fSession = session;
  414.     InitBindingNamespaceUtils(session);
  415.     fSelf = session->GetBinding(ev);
  416.     
  417.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  418.  
  419.     fSubstitutionList = (ODValueNameSpace*)nsm->CreateNameSpace(ev, 
  420.         (ODISOStr)kEditorSubstitutionList, kODNULL, 1, kODNSDataTypeODValue);
  421.  
  422.     fNMResponseUPP = NewNMProc(BindingNMResponse);
  423.     fNMRecPtr = (NMRecPtr) ODNewPtr(sizeof(NMRec));
  424.     THROW_IF_NULL(fNMRecPtr);
  425.     fNMRecPtr->nmStr = kODNULL;    
  426. }
  427.  
  428. //------------------------------------------------------------------------------
  429. // Binding::Purge
  430. //------------------------------------------------------------------------------
  431. ODSize Binding::Purge(ODSize size)
  432. {
  433. ODUnused(size);
  434.     // The only memory that Binding has to purge is owned by NmSpcMgr and
  435.     // is being purge from there.
  436.     return 0;
  437. }
  438.  
  439.  
  440.     //---------------------------------
  441.     // Direct editor bindings
  442.  
  443. //------------------------------------------------------------------------------
  444. // Binding::ChooseEditorForPart
  445. //------------------------------------------------------------------------------
  446. ODEditor Binding::ChooseEditorForPart(ODStorageUnit* thePartSU, ODType newKind )
  447. {
  448.     ODEditor theChosenEditor = (ODEditor)kODNULL; ODVolatile( theChosenEditor );
  449.     ODBoolean noPreferredEditorProp = kODFalse;
  450.     
  451.     TRY
  452.         if (thePartSU)
  453.             theChosenEditor = GetPreferredEditorForPart(thePartSU, &noPreferredEditorProp);
  454.         if (theChosenEditor)
  455.         { 
  456.             LOG("Using prefered editor %s",theChosenEditor);
  457.             return theChosenEditor;
  458.         }
  459.     
  460.             theChosenEditor = ChooseDirectEditorForPart(thePartSU, newKind);
  461.     
  462. /*
  463.         // NO AUTOMATIC TRANSLATION in v1
  464.         
  465.         if (!theChosenEditor && AutomaticTranslation()) 
  466.             theChosenEditor = TranslateAndChooseEditorForPart(thePartSU);
  467. */    
  468.     
  469.         if (!theChosenEditor) 
  470.         {
  471.             WARN("Chosen editor is kODNULL ; returning NoPart");
  472.  
  473.             theChosenEditor = (ODEditor) ODNewPtrClear( 
  474.                                     sizeof(kODBlackBoxHandlerOfLastResort) + 1);
  475.             ODBlockMove( kODBlackBoxHandlerOfLastResort,  
  476.                 theChosenEditor, sizeof(kODBlackBoxHandlerOfLastResort) + 1 );
  477.         }
  478.         else
  479.         {
  480.             Environment* ev = somGetGlobalEnvironment ();
  481.     
  482.             LOG("Chosen editor is %s",theChosenEditor);
  483.  
  484.             if (thePartSU)
  485.             { 
  486.             
  487.             // This routine is a no-op if the ChoosenEditor is a
  488.             // viewerOfLastResort or the draft has read only permissions.
  489.             ODSetPreferredEditorProps(thePartSU,theChosenEditor);
  490.             
  491.             /*                
  492.             if ((!readOnlyStorage) && !ODISOStrEqual(theChosenEditor, kODBlackBoxHandlerOfLastResort))
  493.             {
  494.                 ODSetISOStrProp(ev, thePartSU, kODPropPreferredEditor, 
  495.                                                         kODEditor, theChosenEditor);
  496.             }
  497.             */
  498.             
  499.             TRY
  500.             if (!noPreferredEditorProp && !IsNoPart(ev,theChosenEditor))
  501.                     this->SubstitutionWarning(theChosenEditor, thePartSU);
  502.             ENDTRY
  503.             CATCH_ALL
  504.             
  505.             }
  506.         }
  507.         
  508.     CATCH_ALL
  509.         ODDeleteObject( theChosenEditor );
  510.         RERAISE;
  511.     ENDTRY
  512.  
  513.     return theChosenEditor;
  514. }
  515.  
  516. //------------------------------------------------------------------------------
  517. // Binding::TranslateAndChooseEditorForPart
  518. //------------------------------------------------------------------------------
  519.  
  520. ODEditor Binding::TranslateAndChooseEditorForPart(ODStorageUnit* thePartSU)
  521. {
  522. ODUnused(thePartSU);
  523.     return (ODEditor)kODNULL;
  524. }    
  525.  
  526. //------------------------------------------------------------------------------
  527. // Binding::ChooseDirectEditorForPart
  528. //------------------------------------------------------------------------------
  529.  
  530. ODEditor Binding::ChooseDirectEditorForPart(ODStorageUnit* thePartSU, 
  531.                                                                 ODType newKind )
  532. {
  533. // NOTE: This method does NOT check the preferred editor of the given part
  534.  
  535.     Environment* ev = somGetGlobalEnvironment ();
  536.     ODEditor theEditor = kODNULL;
  537.     
  538.     if (thePartSU)
  539.     {
  540.             // Check for preferredKind property
  541.         ODType preferredKind;
  542.         if ((preferredKind = ODGetISOStrProp(ev, thePartSU, 
  543.                                 kODPropPreferredKind, kODISOStr, kODNULL, kODNULL))
  544.             != kODNULL)
  545.         {            
  546.             theEditor = ChooseDirectEditorForKind(preferredKind,thePartSU);
  547.             ODDisposePtr(preferredKind);
  548.         }
  549.         
  550.         if (theEditor) 
  551.                 return theEditor;
  552.             // Attempt to bind using the content values in their fidelity order
  553.         for (ODValueIndex valueIndex = 1;
  554.             thePartSU->Exists(ev, kODPropContents,(ODValueType)kODNULL,valueIndex)
  555.                                                           && (theEditor == kODNULL);
  556.             valueIndex++)
  557.         {
  558.             thePartSU->Focus(ev, kODPropContents,kODPosSame,(ODValueType)kODNULL,
  559.                                                              valueIndex,kODPosSame);
  560.             TempODValueType type = thePartSU->GetType(ev);
  561.             theEditor = ChooseDirectEditorForKind(type,thePartSU);
  562.         }
  563.         if (theEditor) 
  564.                 return theEditor;
  565.     }
  566.     
  567.     if (newKind)
  568.         theEditor = ChooseDirectEditorForKind(newKind,thePartSU);
  569.  
  570.     if (!theEditor) 
  571.         theEditor = ChooseDirectEditorForKind(kODViewerOfLastResortKind,thePartSU);
  572.     
  573.     if (theEditor) 
  574.         return theEditor;
  575.     else
  576.         return kODNULL;
  577. }
  578.     
  579. //------------------------------------------------------------------------------
  580. // Binding::ChooseDirectEditorForKind
  581. //------------------------------------------------------------------------------
  582.  
  583. ODEditor Binding::ChooseDirectEditorForKind(ODType aKind, 
  584.                                                        ODStorageUnit* thePartSU)
  585. {
  586.     ODEditor theEditor = kODNULL;    ODVolatile( theEditor );
  587.     EditorSet* editorSet = kODNULL; ODVolatile( editorSet );
  588.     Environment* ev = somGetGlobalEnvironment ();
  589.  
  590.     if (!aKind )
  591.         return theEditor;
  592.         
  593.     TRY
  594.         ODNameSpaceManager* theNameSpaceManager = fSession->GetNameSpaceManager(ev);
  595.         
  596.         if (thePartSU)
  597.         {
  598.             EditorSet* theEditorSet = GetAllRestrictedEditorsForKind(thePartSU->
  599.                                                                 GetDraft(ev),aKind);
  600.             if (theEditorSet != kODNULL) 
  601.             {
  602.                 theEditor = AlphaNumChooseEditor(theEditorSet);
  603.                 SetSysPrefEditorForKind(theNameSpaceManager, aKind,theEditor);
  604.                 return theEditor;
  605.             }
  606.         }
  607.         
  608.         theEditor = GetSysPrefEditorForKind(theNameSpaceManager, aKind);
  609.         if (theEditor && EditorExists(theEditor)) 
  610.             return theEditor;
  611.         else
  612.         {
  613.             ODDisposePtr( theEditor );
  614.             theEditor = kODNULL;
  615.         }
  616.     
  617.         ODTypeList* categories = GetCategoriesOfKind(theNameSpaceManager, aKind);
  618.         if (categories)
  619.         {
  620.             ODBoolean     editorFound = kODFalse;
  621.             for (TempODTypeListIterator catItr(ev,categories);
  622.                 catItr.Current() && !editorFound;
  623.                 catItr.Next())
  624.             {
  625.                 theEditor = GetSysPrefEditorForCategory(theNameSpaceManager,
  626.                                                                          catItr.Current());
  627.                 editorFound = (theEditor &&
  628.                     EditorSupportsKind(theNameSpaceManager, theEditor,aKind) &&
  629.                     EditorExists(theEditor));
  630.             }
  631.             if (editorFound)
  632.                 return theEditor;
  633.             else
  634.             {
  635.                 ODDisposePtr( theEditor );
  636.                 theEditor = kODNULL;
  637.             }
  638.         }
  639.     
  640.         editorSet = new EditorSet;
  641.         editorSet->InitEditorSet();
  642.         
  643.         if (GetAllEditorsForKind( theNameSpaceManager, aKind, editorSet )) 
  644.         {
  645.             theEditor = AlphaNumChooseEditor(editorSet);
  646.             if (EditorExists(theEditor)) {
  647.                 SetSysPrefEditorForKind(theNameSpaceManager, aKind,theEditor);
  648.                 theEditor = ODISOStrFromCStr(theEditor);    // Duplicate the string!
  649.             } else
  650.                 theEditor = kODNULL;
  651.         }
  652.         
  653.         ODDeleteObject( editorSet );
  654.     CATCH_ALL
  655.         ODDeleteObject( editorSet );
  656.         ODDisposePtr( theEditor );
  657.         RERAISE;
  658.     ENDTRY
  659.     
  660.     return theEditor;
  661. }
  662.  
  663.     //---------------------------------
  664.     // Editor related utility methods
  665.  
  666. //------------------------------------------------------------------------------
  667. // Binding::EditorExists
  668. //
  669. //     lookup editor in editorkinds namespace and return kODTrue if it exists
  670. //------------------------------------------------------------------------------
  671.  
  672. ODBoolean Binding::EditorExists(ODEditor editor)
  673. {
  674.     Environment* ev = somGetGlobalEnvironment ();
  675.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  676.     
  677.     /*  Try twice to find the editor. If the first search fails, re-synch the
  678.         name-space (by hitting the disk and searching all available "Editors"
  679.         folders) and try again. If the second search fails, give up. --jpa */
  680.     
  681.     /*    ????? This could be slow if we are called many times in a row with
  682.         genuinely nonexistent editors. If this turns out to be a real problem,
  683.         one could keep around the time of last synching, and not synch more than
  684.         once every five seconds. */
  685.     
  686.     ODBoolean synched = kODFalse;
  687.     for( ;; ) {
  688.         ODNameSpace* editorkindsNameSpace = 
  689.             fSession->GetNameSpaceManager(ev)->HasNameSpace( ev, kODEditorKinds );
  690.         
  691.         if ( editorkindsNameSpace
  692.                 && editorkindsNameSpace->Exists(ev, (ODISOStr)editor) )
  693.             return kODTrue;
  694.         
  695.         if( !synched ) {
  696.             synched = kODTrue;
  697.             nsm->SynchNSTable(ev);
  698.             continue;
  699.         } else
  700.             return kODFalse;
  701.     }
  702. }
  703.         
  704. //------------------------------------------------------------------------------
  705. // Binding::IsEditorLoaded
  706. //------------------------------------------------------------------------------
  707. ODBoolean Binding::IsEditorLoaded(ODEditor editor)
  708. {
  709.     return ODClassExists(editor);
  710. }
  711.  
  712. //------------------------------------------------------------------------------
  713. // Binding::GetPreferredEditorForPart
  714. //------------------------------------------------------------------------------
  715. ODEditor Binding::GetPreferredEditorForPart(ODStorageUnit* thePartSU, 
  716.                                               ODBoolean* noPreferredEditorProp)
  717. {
  718.     // read preferred editor from thePartSU
  719.     Environment* ev = somGetGlobalEnvironment ();
  720.     ODEditor preferredEditor = kODNULL;
  721.     if (thePartSU->Exists(ev, kODPropPreferredEditor,kODEditor,0))
  722.     {
  723.         ODULong size;
  724.         preferredEditor = ODGetISOStrProp(ev, thePartSU, 
  725.                             kODPropPreferredEditor, kODEditor, kODNULL, &size);
  726.         if (preferredEditor)
  727.         {
  728.             if (EditorExists(preferredEditor))
  729.             {
  730.                 *noPreferredEditorProp = kODFalse;
  731.             } else {
  732.                 ODDisposePtr(preferredEditor);
  733.                 preferredEditor = kODNULL;
  734.                     // the prop exists in SU but is empty
  735.                 if (size == 0)
  736.                     *noPreferredEditorProp = kODTrue;
  737.             }
  738.         }
  739.     }
  740.     else 
  741.     {
  742.         *noPreferredEditorProp = kODTrue;
  743.         if (HAS_WRITE_ACCESS(thePartSU->GetDraft(ev)->GetPermissions(ev)))
  744.             ODSUAddPropValue(ev, thePartSU, kODPropPreferredEditor, kODEditor);
  745.     }
  746.     return preferredEditor;
  747. }
  748.  
  749.  
  750. //------------------------------------------------------------------------------
  751. // Binding::GetKindsSupported
  752. //
  753. //     lookup editor in editorkinds namespace and return kinds supported
  754. //------------------------------------------------------------------------------
  755.  
  756. ODTypeList* Binding::GetKindsSupported(ODEditor editor)
  757. {
  758.     ODTypeList*    kindsList = kODNULL;
  759.     Environment* ev = somGetGlobalEnvironment ();
  760.     
  761.         // get the editorkinds namespace
  762.     ODObjectNameSpace* editorkindsNameSpace = 
  763.         (ODObjectNameSpace*)fSession->GetNameSpaceManager(ev)->HasNameSpace( ev,
  764.                                                                kODEditorKinds );
  765.     
  766.     if (editorkindsNameSpace)
  767.     {
  768.             // Lookup the kinds list by editor class ID
  769.         if (editorkindsNameSpace->GetEntry( ev, (ODISOStr)editor, 
  770.                                     (ODObject**)&kindsList ))
  771.             return kindsList;
  772.         else
  773.             return kODNULL;
  774.     }
  775.     return kindsList;
  776. }
  777.  
  778. //------------------------------------------------------------------------------
  779. // Binding::AlphaNumChooseEditor
  780. //------------------------------------------------------------------------------
  781.  
  782. ODEditor Binding::AlphaNumChooseEditor(EditorSet* editorSet)
  783. {
  784.     // Note: We Alphanumchoose on ISO strings, not user strings so the winning
  785.     // editor may be unpredictable to end users.
  786.     
  787.     // We "prime the pump" with a null viewer part handler that can never win an
  788.     // alphanumeric choose. Previously NoPart (Apple::NoPart) could incorrectly
  789.     // win over a viewer or editor whose name was further down in the alphabet.
  790.     
  791.     Environment* ev = somGetGlobalEnvironment();
  792.     
  793.     ODEditor bestHandler = (ODEditor)kNullViewerPartHandler;
  794.  
  795.     EditorSetIterator* eit = editorSet->CreateIterator();
  796.     
  797.     for (ODEditor handler = eit->First();
  798.         eit->IsNotComplete();
  799.         handler = eit->Next())
  800.     {
  801.         if (IsNoPart(ev, handler))
  802.             handler = kNullViewerPartHandler; // use proxy instead of Apple::NoPart
  803.         
  804.         bestHandler = AlphaNumChooseAnEditorFromTwo(handler,bestHandler);
  805.     }
  806.     ODDeleteObject( eit );
  807.     
  808.     if (strcmp((char*)bestHandler,(char*)kNullViewerPartHandler)==0)
  809.         bestHandler = kODBlackBoxHandlerOfLastResort;  // Convert null viewer part handler to NoPart
  810.     
  811.     return bestHandler;
  812. }
  813.  
  814. //------------------------------------------------------------------------------
  815. // Binding::AlphaNumChooseAnEditorFromTwo
  816. //------------------------------------------------------------------------------
  817.  
  818. ODEditor Binding::AlphaNumChooseAnEditorFromTwo(ODEditor e1, ODEditor e2)
  819. {
  820.     Environment* ev = somGetGlobalEnvironment ();
  821.     ODValueNameSpace*    theViewerNameSpace = ViewerNameSpace();
  822.     TempODByteArrayStruct ignore;
  823.     ODBoolean e1IsViewer = kODFalse;
  824.     ODBoolean e2IsViewer = kODFalse;
  825.  
  826.     if (theViewerNameSpace)
  827.     {
  828.         e1IsViewer = theViewerNameSpace->GetEntry(ev, (ODISOStr)e1, ignore);
  829.         e2IsViewer = theViewerNameSpace->GetEntry(ev, (ODISOStr)e2, ignore);
  830.     }
  831.     
  832.     if (!e1IsViewer && e2IsViewer)
  833.         return e1;
  834.     else if (!e2IsViewer && e1IsViewer)
  835.         return e2;
  836.     else if (strcmp((char*)e1,(char*)e2)<=0)
  837.         return e1;
  838.     else
  839.         return e2;
  840. }
  841.         
  842. //------------------------------------------------------------------------------
  843. // Binding::DraftRestrictsEditors
  844. //------------------------------------------------------------------------------
  845.  
  846. ODBoolean Binding::DraftRestrictsEditors(ODDraft* draft)
  847. {
  848. ODUnused(draft);
  849.     // return whether or not restrictedEditors property exists
  850.     return kODFalse;
  851. }
  852.  
  853. //------------------------------------------------------------------------------
  854. // Binding::GetAllRestrictedEditorsForKind
  855. //------------------------------------------------------------------------------
  856.  
  857. EditorSet* Binding::GetAllRestrictedEditorsForKind(ODDraft* draft, ODType kind)
  858. {
  859. ODUnused(draft);
  860. ODUnused(kind);
  861.     // read and return restrictedEditors property of draftProperties
  862.     return kODNULL;
  863. }
  864.         
  865.     //---------------------------------
  866.     // Category and kind mappings
  867.  
  868. //------------------------------------------------------------------------------
  869. // Binding::ViewerNameSpace
  870. //------------------------------------------------------------------------------
  871. ODValueNameSpace*    Binding::ViewerNameSpace()
  872. {
  873.     Environment* ev = somGetGlobalEnvironment ();
  874.     return (ODValueNameSpace*)fSession->GetNameSpaceManager(ev)->HasNameSpace( 
  875.                                                                 ev, kODViewer );
  876. }
  877.  
  878.  
  879. //------------------------------------------------------------------------------
  880. // Binding::GetContainerSuite
  881. //------------------------------------------------------------------------------
  882.  
  883. ODContainerSuite Binding::GetContainerSuite(ODContainerType containerType)
  884. {
  885.     /* Two things can happen here. If containerType is the name of an actual
  886.         container suite, we look it up in the ContainerSuite namespace and
  887.         return the classname. But containerType might also be a constant
  888.         indicating a type of default container suite (e.g. kODDefaultFileContainer)
  889.         in which case we have to first look it up in the system-preferred
  890.         ContainerSuite namespace to get the real container suite name, then
  891.         do the lookup as above to get the classname. */
  892.     
  893.     ODContainerSuite     theContainerSuite;
  894.     
  895.     // First look it up in the ContainerSuite namespace:
  896.     theContainerSuite = ValueNameSpaceGetString(fSession,kODContainerSuite,containerType);
  897.     if( !theContainerSuite ) {
  898.         ODContainerSuite realType;
  899.         ODBoolean isDefault = kODFalse;
  900.         // Not found, look it up in the System-preferred Container Suites namespace:
  901.         realType = ValueNameSpaceGetString(fSession,kODSysPrefContainerSuites,containerType);
  902.         if( !realType ) {
  903.             // Not found there either, check some hardcoded defaults:
  904.             isDefault = kODTrue;
  905.             if( ODISOStrEqual(containerType,kODDefaultMemoryContainer) )
  906.                 realType = kODBentoMemoryContainer;
  907.             else if( ODISOStrEqual(containerType,kODDefaultFileContainer) )
  908.                 realType = kODBentoFileContainer;
  909.         }
  910.         if( realType ) {
  911.             // Now that we have a real containerType, look it up in ContainerSuite:
  912.             theContainerSuite = ValueNameSpaceGetString(fSession,kODContainerSuite,realType);
  913.             if( !isDefault )
  914.                 ODDisposePtr(realType);
  915.         }
  916.     }
  917.     return theContainerSuite;
  918. }
  919.  
  920. //------------------------------------------------------------------------------
  921. // Binding::SubstitutionWarning 
  922. //------------------------------------------------------------------------------
  923.  
  924. void Binding::SubstitutionWarning(ODEditor theEditor, ODStorageUnit* thePartSU)
  925. {
  926.     Environment* ev = somGetGlobalEnvironment ();
  927.  
  928.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  929.     TempODIText category = ODGetCatFromPartSU( ev, thePartSU, nsm); // DMc: temp to ensure it's deleted
  930.     TempODISOStr theCategory = (ODISOStr)ODNewPtrClear(GetITextStringLength(category)+1);
  931.     GetITextCString( category, (char*)theCategory );
  932.  
  933.     if (!NotifiedSubstitutions(theEditor, theCategory))
  934.     {
  935.         ODIText* editorUserString = kODNULL;
  936.         Str255     editorString = "\p";
  937.         Str255     catString = "\p";
  938.         
  939.         GetITextPString( category, catString );
  940.  
  941.         GetUserEditorFromEditor( nsm, theEditor, &editorUserString );
  942.         TempODIText tempEditorUserString = editorUserString; // DMc: ensure it's deleted
  943.         GetITextPString( editorUserString, editorString );
  944.     
  945.         NMRemove(fNMRecPtr);    // ensure not already queued
  946.         fNMRecPtr->qType = nmType;
  947.         fNMRecPtr->nmMark = 0;
  948.         fNMRecPtr->nmIcon = nil;
  949.         fNMRecPtr->nmSound = nil;
  950.         ODDisposePtr((ODPtr) fNMRecPtr->nmStr);
  951.         fNMRecPtr->nmStr = BuildNotificationString(kBindingWarning, catString, editorString);
  952.         fNMRecPtr->nmResp = fNMResponseUPP;
  953.         ODError error = NMInstall(fNMRecPtr);
  954.  
  955.         if (fSubstitutionList)
  956.         {
  957.             ValueNameSpaceRegister(fSubstitutionList, ev, (ODISOStr)theCategory, 
  958.                                   (ODPtr)theEditor, ODISOStrLength(theEditor) + 1);
  959.         }
  960.     }
  961. }
  962.  
  963.  
  964. //------------------------------------------------------------------------------
  965. // Binding::NotifiedSubstitutions
  966. //------------------------------------------------------------------------------
  967.  
  968. ODBoolean Binding::NotifiedSubstitutions(ODEditor theEditor, ODISOStr theCategory)
  969. {
  970.     Environment* ev = somGetGlobalEnvironment ();
  971.     ODNameSpaceManager *nsm = fSession->GetNameSpaceManager(ev);
  972.  
  973.     ODBoolean    subAlreadyNotified = kODFalse;
  974.     
  975.     if (fSubstitutionList)
  976.     {
  977.             // Lookup the substitutionList by editor class ID
  978.         ODISOStr editorSub = ValueNameSpaceGetString(fSession, 
  979.                                             kEditorSubstitutionList, theCategory);
  980.         //WARN("ValueNameSpaceGetString returned '%s'", editorSub);
  981.         if (ODISOStrEqual(editorSub, theEditor))
  982.             subAlreadyNotified = kODTrue;
  983.             
  984.         ODDisposePtr( editorSub );
  985.     }
  986.  
  987.     return subAlreadyNotified;
  988. }
  989.  
  990.